home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / VMRXcl / BltAlpha.h < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  33.1 KB  |  977 lines

  1. //----------------------------------------------------------------------------
  2. //  File:   BltAlpha.h
  3. //
  4. //  Desc:   DirectShow sample code
  5. //          Header file and class description for CAlphaBlt,
  6. //          texture surface to be used in PresentImage of the
  7. //          customized allocator-presenter
  8. //
  9. //  Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
  10. //----------------------------------------------------------------------------
  11.  
  12. #ifndef __INITDDSTRUCT_DEFINED
  13. #define __INITDDSTRUCT_DEFINED
  14. #include <math.h>
  15. #include <d3dxmath.h>
  16. #include "d3dtextr.h"
  17. #include "d3dfont.h"
  18. #include "utils.h"
  19. #include "resrc1.h"
  20. #include "d3dutil.h"
  21.  
  22. extern struct SceneSettings g_ss;
  23.  
  24. template <typename T>
  25. __inline void INITDDSTRUCT(T& dd)
  26. {
  27.     ZeroMemory(&dd, sizeof(dd));
  28.     dd.dwSize = sizeof(dd);
  29. }
  30. #endif
  31.  
  32. #ifndef __RELEASE_DEFINED
  33. #define __RELEASE_DEFINED
  34. template<typename T>
  35. __inline void RELEASE( T* &p )
  36. {
  37.     if( p ) {
  38.         p->Release();
  39.         p = NULL;
  40.     }
  41. }
  42. #endif
  43.  
  44. #ifndef CHECK_HR
  45.     #define CHECK_HR(expr) do { if (FAILED(expr)) __leave; } while(0);
  46. #endif
  47.  
  48. #define COMPLVERTSIZE 640 // must be divisible by 4!!!
  49. #define pi 3.1415926535f
  50.  
  51. //----------------------------------------------------------------------------
  52. // CAlphaBlt
  53. // 
  54. // Desc: texture surface to be used in PresentImage of the
  55. //       customized allocator-presenter
  56. //----------------------------------------------------------------------------
  57. class CAlphaBlt
  58. {
  59. private:
  60.  
  61.     LPDIRECTDRAW7               m_pDD;
  62.     LPDIRECT3D7                 m_pD3D;
  63.     LPDIRECT3DDEVICE7           m_pD3DDevice;
  64.     LPDIRECTDRAWSURFACE7        m_lpDDBackBuffer;
  65.  
  66.     LPDIRECTDRAWSURFACE7        m_lpDDMirror;
  67.     LPDIRECTDRAWSURFACE7        m_lpDDM32;
  68.     LPDIRECTDRAWSURFACE7        m_lpDDM16;
  69.     DDSURFACEDESC2              m_ddsdM32;
  70.     DDSURFACEDESC2              m_ddsdM16;
  71.  
  72.     bool                        m_fPowerOf2;
  73.     bool                        m_fSquare;
  74.     bool                        m_bNeedToRestoreMenu;
  75.     TextureContainer *          m_ptxtrMenu;
  76.     CD3DFont *                  m_pFont;
  77.  
  78.     typedef struct Vertex
  79.     {
  80.         float x, y, z, rhw;
  81.         D3DCOLOR clr;
  82.         float tu, tv;
  83.     } Vertex;
  84.  
  85.     Vertex pVertices[4];            // primitive for rotating effect
  86.     Vertex pVComplex[COMPLVERTSIZE];// primitive for twisting effect
  87.     Vertex pVMenu[4];               // primitive for menu effect
  88.  
  89.  
  90.     //----------------------------------------------------------------------------
  91.     // CAlphaBlt::Rotate
  92.     // 
  93.     // Desc: 3D transformation of pVertices that provide rotation around Z and Y 
  94.     // 
  95.     // Parameters:
  96.     //      theta       - angle of rotation around Z axis
  97.     //      thetaY      - angle of rotation around Y axis
  98.     //      pVertices   - array of (Vertex*) to be transformed
  99.     //      nSize       - number of vertices
  100.     //      (cx2, cy2)  - center of rotation
  101.     //----------------------------------------------------------------------------
  102.     void Rotate(float theta, float thetaY, 
  103.                 CAlphaBlt::Vertex * pVertices, 
  104.                 int nSize, float cx2, float cy2)
  105.     {
  106.         D3DXMATRIX  mtrV;
  107.         D3DXMATRIX  mtrRotZ;
  108.         D3DXMATRIX  mtrRotY;
  109.         D3DXMATRIX  mtrPrs;
  110.         D3DXMATRIX  mtrRes;
  111.  
  112.         float pi2 = 1.57079632675f; // pi/2.
  113.  
  114.         // initialize mtrV
  115.         mtrV.m[0][0] = pVertices[0].x - cx2;    
  116.         mtrV.m[1][0] = pVertices[0].y - cy2;    
  117.         mtrV.m[2][0] = pVertices[0].z;          
  118.         mtrV.m[3][0] = 0.f;                     
  119.  
  120.         mtrV.m[0][1] = pVertices[1].x - cx2;    
  121.         mtrV.m[1][1] = pVertices[1].y - cy2;    
  122.         mtrV.m[2][1] = pVertices[1].z;  
  123.         mtrV.m[3][1] = 0;
  124.  
  125.         mtrV.m[0][2] = pVertices[2].x - cx2;    
  126.         mtrV.m[1][2] = pVertices[2].y - cy2;    
  127.         mtrV.m[2][2] = pVertices[2].z;  
  128.         mtrV.m[3][2] = 0;               
  129.  
  130.         mtrV.m[0][3] = pVertices[3].x - cx2;
  131.         mtrV.m[1][3] = pVertices[3].y - cy2;
  132.         mtrV.m[2][3] = pVertices[3].z;
  133.         mtrV.m[3][3] = 0;
  134.         
  135.         D3DXMatrixRotationZ( &mtrRotZ,  theta); 
  136.         D3DXMatrixRotationY( &mtrRotY,  thetaY); 
  137.         D3DXMatrixPerspectiveFov( &mtrPrs, pi2, 1.1f, 0.f, 1.f);
  138.  
  139.  
  140.         // mtrRotZ * mtrV
  141.         D3DXMatrixMultiply( &mtrRes, &mtrRotZ, &mtrV);
  142.  
  143.         // mtrRotY * mtrRotZ * mtrV
  144.         D3DXMatrixMultiply( &mtrV, &mtrRotY, &mtrRes);
  145.  
  146.         // mtrPrs * mtrRotY * mtrRotZ * mtrV
  147.         D3DXMatrixMultiply( &mtrRes, &mtrPrs, &mtrV);
  148.         
  149.         // here, mtrRes has what we need; copy it back to pVertices
  150.         pVertices[0].x = mtrRes.m[0][0] + cx2;  
  151.         pVertices[1].x = mtrRes.m[0][1] + cx2;  
  152.         pVertices[2].x = mtrRes.m[0][2] + cx2;  
  153.         pVertices[3].x = mtrRes.m[0][3] + cx2;
  154.  
  155.         pVertices[0].y = mtrRes.m[1][0] + cy2;  
  156.         pVertices[1].y = mtrRes.m[1][1] + cy2;  
  157.         pVertices[2].y = mtrRes.m[1][2] + cy2;  
  158.         pVertices[3].y = mtrRes.m[1][3] + cy2;
  159.         
  160.         pVertices[0].z = mtrRes.m[2][0];    
  161.         pVertices[1].z = mtrRes.m[2][1];    
  162.         pVertices[2].z = mtrRes.m[2][2];    
  163.         pVertices[3].z = mtrRes.m[2][3];
  164.         return;
  165.     }   
  166.     
  167.     //----------------------------------------------------------------------------
  168.     // IsSurfaceBlendable
  169.     //
  170.     // Checks the DD surface description and the given
  171.     // alpha value to determine if this surface is blendable.
  172.     //
  173.     //----------------------------------------------------------------------------
  174.     bool
  175.     IsSurfaceBlendable(
  176.         DDSURFACEDESC2& ddsd,
  177.         BYTE fAlpha
  178.         )
  179.     {
  180.         // Is the surface already a D3D texture ?
  181.         if (ddsd.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
  182.             return true;
  183.         }
  184.  
  185.         // OK we have to mirror the surface
  186.         return false;
  187.     }
  188.  
  189.     //----------------------------------------------------------------------------
  190.     // MirrorSourceSurface
  191.     //
  192.     // The mirror surface cab be either 16 or 32 bit RGB depending
  193.     // upon the format of the source surface.
  194.     //
  195.     // Of course it should have the "texture" flag set and should be in VRAM.  
  196.     // If we can't create the surface then the AlphaBlt should fail
  197.     //----------------------------------------------------------------------------
  198.     HRESULT MirrorSourceSurface(
  199.         LPDIRECTDRAWSURFACE7 lpDDS,
  200.         DDSURFACEDESC2& ddsd
  201.         )
  202.     {
  203.         HRESULT hr = DD_OK;
  204.         DWORD dwMirrorBitDepth = 0;
  205.         DDSURFACEDESC2 ddsdMirror={0};
  206.  
  207.  
  208.         //
  209.         // OK - is it suitable for our needs.
  210.         //
  211.         // Apply the following rules:
  212.         //  if ddsd is a FOURCC surface the mirror should be 32 bit
  213.         //  if ddsd is RGB then the mirror's bit depth should match
  214.         //      that of ddsd.
  215.         //
  216.         // Also, the mirror must be large enough to actually hold
  217.         // the surface to be blended
  218.         //
  219.  
  220.         m_lpDDMirror = NULL;
  221.  
  222.         if (ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ||
  223.             ddsd.ddpfPixelFormat.dwRGBBitCount == 32) {
  224.  
  225.             if (ddsd.dwWidth > m_ddsdM32.dwWidth ||
  226.                 ddsd.dwHeight > m_ddsdM32.dwHeight) {
  227.  
  228.                 RELEASE(m_lpDDM32);
  229.             }
  230.  
  231.             if (!m_lpDDM32) {
  232.                 dwMirrorBitDepth = 32;
  233.             }
  234.             else {
  235.                 m_lpDDMirror = m_lpDDM32;
  236.                 ddsdMirror = m_ddsdM32;
  237.             }
  238.         }
  239.         else if (ddsd.ddpfPixelFormat.dwRGBBitCount == 16) {
  240.  
  241.             if (ddsd.dwWidth > m_ddsdM16.dwWidth ||
  242.                 ddsd.dwHeight > m_ddsdM16.dwHeight) {
  243.  
  244.                 RELEASE(m_lpDDM16);
  245.             }
  246.  
  247.             if (!m_lpDDM16) {
  248.                 dwMirrorBitDepth = 16;
  249.             }
  250.             else {
  251.                 m_lpDDMirror = m_lpDDM16;
  252.                 ddsdMirror = m_ddsdM16;
  253.             }
  254.         }
  255.         else {
  256.  
  257.             // No support for RGB24 or RGB8!
  258.             return E_INVALIDARG;
  259.         }
  260.  
  261.         if (!m_lpDDMirror) {
  262.  
  263.             INITDDSTRUCT(ddsdMirror);
  264.             ddsdMirror.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  265.             ddsdMirror.ddpfPixelFormat.dwFlags = DDPF_RGB;
  266.             ddsdMirror.ddpfPixelFormat.dwRGBBitCount = dwMirrorBitDepth;
  267.  
  268.             switch (dwMirrorBitDepth) {
  269.             case 16:
  270.                 ddsdMirror.ddpfPixelFormat.dwRBitMask = 0x0000F800;
  271.                 ddsdMirror.ddpfPixelFormat.dwGBitMask = 0x000007E0;
  272.                 ddsdMirror.ddpfPixelFormat.dwBBitMask = 0x0000001F;
  273.                 break;
  274.  
  275.             case 32:
  276.                 ddsdMirror.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
  277.                 ddsdMirror.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
  278.                 ddsdMirror.ddpfPixelFormat.dwBBitMask = 0x000000FF;
  279.                 break;
  280.             }
  281.  
  282.             ddsdMirror.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
  283.             ddsdMirror.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
  284.  
  285.             if (m_fPowerOf2) {
  286.  
  287.                 for (ddsdMirror.dwWidth = 1;
  288.                      ddsd.dwWidth > ddsdMirror.dwWidth;
  289.                      ddsdMirror.dwWidth <<= 1);
  290.  
  291.                 for (ddsdMirror.dwHeight = 1;
  292.                      ddsd.dwHeight > ddsdMirror.dwHeight;
  293.                      ddsdMirror.dwHeight <<= 1);
  294.             }
  295.             else {
  296.                 ddsdMirror.dwWidth = ddsd.dwWidth;
  297.                 ddsdMirror.dwHeight = ddsd.dwHeight;
  298.             }
  299.  
  300.             if (m_fSquare) {
  301.  
  302.                 if (ddsdMirror.dwHeight > ddsdMirror.dwWidth) {
  303.                     ddsdMirror.dwWidth = ddsdMirror.dwHeight;
  304.                 }
  305.  
  306.                 if (ddsdMirror.dwWidth > ddsdMirror.dwHeight) {
  307.                     ddsdMirror.dwHeight = ddsdMirror.dwWidth;
  308.                 }
  309.             }
  310.  
  311.             __try {
  312.  
  313.                 // Attempt to create the surface with theses settings
  314.                 CHECK_HR(hr = m_pDD->CreateSurface(&ddsdMirror, &m_lpDDMirror, NULL));
  315.  
  316.                 INITDDSTRUCT(ddsdMirror);
  317.                 CHECK_HR(hr =  m_lpDDMirror->GetSurfaceDesc(&ddsdMirror));
  318.  
  319.                 switch (dwMirrorBitDepth) {
  320.                 case 16:
  321.                     m_ddsdM16 = ddsdMirror;
  322.                     m_lpDDM16 = m_lpDDMirror;
  323.                     break;
  324.  
  325.                 case 32:
  326.                     m_ddsdM32 = ddsdMirror;
  327.                     m_lpDDM32 = m_lpDDMirror;
  328.                     break;
  329.                 }
  330.  
  331.             } __finally {}
  332.         }
  333.  
  334.         if (hr == DD_OK) {
  335.  
  336.             __try {
  337.                 RECT rc = {0, 0, ddsd.dwWidth, ddsd.dwHeight};
  338.                 CHECK_HR(hr = m_lpDDMirror->Blt(&rc, lpDDS, &rc, DDBLT_WAIT, NULL));
  339.                 ddsd = ddsdMirror;
  340.             } __finally {}
  341.         }
  342.  
  343.         return hr;
  344.     }
  345.  
  346. public:
  347.  
  348.     //----------------------------------------------------------------------------
  349.     // Constructor
  350.     //----------------------------------------------------------------------------
  351.     CAlphaBlt(LPDIRECTDRAWSURFACE7 lpDDSDst, HRESULT* phr) :
  352.         m_pDD(NULL),
  353.         m_pD3D(NULL),
  354.         m_pD3DDevice(NULL),
  355.         m_lpDDBackBuffer(NULL),
  356.         m_lpDDMirror(NULL),
  357.         m_lpDDM32(NULL),
  358.         m_lpDDM16(NULL),
  359.         m_ptxtrMenu( NULL),
  360.         m_pFont(NULL),
  361.         m_fPowerOf2(false),
  362.         m_fSquare(false),
  363.         m_bNeedToRestoreMenu(false)
  364.     {
  365.         ZeroMemory(&m_ddsdM32, sizeof(m_ddsdM32));
  366.         ZeroMemory(&m_ddsdM16, sizeof(m_ddsdM16));
  367.  
  368.         HRESULT hr;
  369.         hr = lpDDSDst->GetDDInterface((LPVOID *)&m_pDD);
  370.         if (FAILED(hr)) {
  371.             m_pDD = NULL;
  372.             *phr = hr;
  373.         }
  374.  
  375.         if (SUCCEEDED(hr)) {
  376.             hr = m_pDD->QueryInterface(IID_IDirect3D7, (LPVOID *)&m_pD3D);
  377.             if (FAILED(hr)) {
  378.                 m_pD3D = NULL;
  379.                 *phr = hr;
  380.             }
  381.         }
  382.  
  383.         if (SUCCEEDED(hr)) {
  384.             hr = m_pD3D->CreateDevice(IID_IDirect3DHALDevice,
  385.                                       lpDDSDst,
  386.                                       &m_pD3DDevice);
  387.             if (FAILED(hr)) {
  388.                 m_pD3DDevice = NULL;
  389.                 *phr = hr;
  390.             }
  391.             else {
  392.                 m_lpDDBackBuffer = lpDDSDst;
  393.                 m_lpDDBackBuffer->AddRef();
  394.             }
  395.         }
  396.  
  397.         if (SUCCEEDED(hr)) {
  398.  
  399.             D3DDEVICEDESC7 ddDesc;
  400.             if (DD_OK == m_pD3DDevice->GetCaps(&ddDesc)) {
  401.  
  402.                 if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) {
  403.                     m_fPowerOf2 = true;
  404.                 }
  405.  
  406.                 if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
  407.                     m_fSquare = true;
  408.                 }
  409.             }
  410.             else {
  411.                 *phr = hr;
  412.             }
  413.         }
  414.  
  415.         // here, so far we have D3Device, let's  Restore texture surface
  416.         // it actually loads the bitmap from the resource onto a texture surface
  417.         m_ptxtrMenu = new TextureContainer(
  418.             "IDB_MENU", 0, 0, IDB_MENU);
  419.  
  420.         if( m_ptxtrMenu) 
  421.         {
  422.             hr = m_ptxtrMenu->LoadImageData();
  423.             if( m_ptxtrMenu->m_hbmBitmap )
  424.             {
  425.                 BITMAP bm;
  426.                 GetObject( m_ptxtrMenu->m_hbmBitmap, sizeof(BITMAP), &bm );
  427.                 m_ptxtrMenu->m_dwWidth  = (DWORD)bm.bmWidth;
  428.                 m_ptxtrMenu->m_dwHeight = (DWORD)bm.bmHeight;
  429.                 m_ptxtrMenu->m_dwBPP    = (DWORD)bm.bmBitsPixel;
  430.             }
  431.             
  432.             hr = m_ptxtrMenu->Restore(m_pD3DDevice);
  433.             if( FAILED(hr))
  434.             {
  435.                 delete m_ptxtrMenu;
  436.                 m_ptxtrMenu = NULL;
  437.             }
  438.         }
  439.  
  440.         // load the font 
  441.         m_pFont = new CD3DFont( TEXT("Comic Sans MS"),18,0);
  442.         if( m_pFont )
  443.         {
  444.             m_pFont->InitDeviceObjects( m_pDD, m_pD3DDevice);
  445.         }
  446.  
  447.         // setup menu primitive
  448.         pVMenu[0].x = 0.f;
  449.         pVMenu[0].y = 0.f;
  450.         pVMenu[0].z = 0.0f;
  451.         pVMenu[0].rhw = 2.0f;
  452.         pVMenu[0].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
  453.  
  454.         pVMenu[1].x = 60.f;
  455.         pVMenu[1].y = 0.f;
  456.         pVMenu[1].z = 0.0f;
  457.         pVMenu[1].rhw = 2.0f;
  458.         pVMenu[1].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
  459.  
  460.         pVMenu[2].x = 0.f;
  461.         pVMenu[2].y = 480.f;
  462.         pVMenu[2].z = 0.0f;
  463.         pVMenu[2].rhw = 2.0f;
  464.         pVMenu[2].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
  465.  
  466.         pVMenu[3].x = 60.f;
  467.         pVMenu[3].y = 480.f;
  468.         pVMenu[3].z = 0.0f;
  469.         pVMenu[3].rhw = 2.0f;
  470.         pVMenu[3].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
  471.  
  472.         //
  473.         // Setup the SRC info
  474.         //
  475.         pVMenu[0].tu = 0.f;
  476.         pVMenu[0].tv = 0.f;
  477.  
  478.         pVMenu[1].tu = 1.f;
  479.         pVMenu[1].tv = 0.f;
  480.  
  481.         pVMenu[2].tu = 0.f;
  482.         pVMenu[2].tv = 1.f;
  483.  
  484.         pVMenu[3].tu = 1.f;
  485.         pVMenu[3].tv = 1.f;
  486.    }
  487.  
  488.     //----------------------------------------------------------------------------
  489.     // Destructor
  490.     //----------------------------------------------------------------------------
  491.    ~CAlphaBlt()
  492.     {
  493.         if( m_ptxtrMenu )
  494.         {
  495.             delete m_ptxtrMenu;
  496.             m_ptxtrMenu = NULL;
  497.         }
  498.  
  499.         if( m_pFont )
  500.         {
  501.             delete m_pFont;
  502.             m_pFont = NULL;
  503.         }
  504.  
  505.         RELEASE(m_lpDDBackBuffer);
  506.         RELEASE(m_lpDDM32);
  507.         RELEASE(m_lpDDM16);
  508.  
  509.         RELEASE(m_pD3DDevice);
  510.         RELEASE(m_pD3D);
  511.         RELEASE(m_pDD);
  512.     }
  513.  
  514.     //----------------------------------------------------------------------------
  515.     // GetMenuTexture
  516.     //
  517.     // returns pointer to texture's DD surface or NULL otherwise
  518.     //----------------------------------------------------------------------------
  519.     LPDIRECTDRAWSURFACE7 GetMenuTexture()
  520.     {
  521.         if( m_ptxtrMenu && m_ptxtrMenu->m_pddsSurface )
  522.         {
  523.             return (m_ptxtrMenu->m_pddsSurface);
  524.         }
  525.         return NULL;
  526.     }
  527.  
  528.     //----------------------------------------------------------------------------
  529.     // SetMenuRestoreFlag
  530.     //
  531.     // sets m_bNeedToRestoreMenu = true; (called from CMpegMovie::RestoreDDRawSurfaces() )
  532.     //----------------------------------------------------------------------------
  533.     void SetMenuRestoreFlag()
  534.     {
  535.         m_bNeedToRestoreMenu = true;
  536.     }
  537.  
  538.     //----------------------------------------------------------------------------
  539.     // GetFont
  540.     //----------------------------------------------------------------------------
  541.     CD3DFont * GetFont()
  542.     {
  543.         return m_pFont;
  544.     }
  545.  
  546.     //----------------------------------------------------------------------------
  547.     // PrepareVerticesRotate
  548.     //
  549.     // This is the 'main' transformation function for foration effect.
  550.     // It generates rotation angles from 'time' variable that is just
  551.     // a static counter of images from CMpegMovie:PresentImage function
  552.     //
  553.     // Parameters:
  554.     //          lpDst   - destination rectangle
  555.     //          lpSrc   - source rectangle
  556.     //          alpha   - alpha level for the surface
  557.     //          fWid    - width of the surface obtained by CMpegMovie:PresentImage
  558.     //          fHgt    - height of the surface obtained by CMpegMovie:PresentImage
  559.     //----------------------------------------------------------------------------
  560.     void PrepareVerticesRotate( RECT* lpDst, RECT* lpSrc, BYTE alpha,
  561.                                 float fWid, float fHgt)
  562.     {
  563.         float RotRadZ = 0.f;
  564.         float RotRadY = 0.f;
  565.             
  566.         //
  567.         // Setup the DST info
  568.         //
  569.         pVertices[0].x = (float)lpDst->left;
  570.         pVertices[0].y = (float)lpDst->top;
  571.         pVertices[0].z = 0.5f;
  572.         pVertices[0].rhw = 2.0f;
  573.         pVertices[0].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
  574.  
  575.         pVertices[1].x = (float)lpDst->right;
  576.         pVertices[1].y = (float)lpDst->top;
  577.         pVertices[1].z = 0.5f;
  578.         pVertices[1].rhw = 2.0f;
  579.         pVertices[1].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
  580.  
  581.         pVertices[2].x = (float)lpDst->left;
  582.         pVertices[2].y = (float)lpDst->bottom;
  583.         pVertices[2].z = 0.5f;
  584.         pVertices[2].rhw = 2.0f;
  585.         pVertices[2].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
  586.  
  587.         pVertices[3].x = (float)lpDst->right;
  588.         pVertices[3].y = (float)lpDst->bottom;
  589.         pVertices[3].z = 0.5f;
  590.         pVertices[3].rhw = 2.0f;
  591.         pVertices[3].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
  592.  
  593.         //
  594.         // Setup the SRC info
  595.         //
  596.         pVertices[0].tu = ((float)lpSrc->left) / fWid;
  597.         pVertices[0].tv = ((float)lpSrc->top) / fHgt;
  598.  
  599.         pVertices[1].tu = ((float)lpSrc->right) / fWid;
  600.         pVertices[1].tv = ((float)lpSrc->top) / fHgt;
  601.  
  602.         pVertices[2].tu = ((float)lpSrc->left) / fWid;
  603.         pVertices[2].tv = ((float)lpSrc->bottom) / fHgt;
  604.  
  605.         pVertices[3].tu = ((float)lpSrc->right) / fWid;
  606.         pVertices[3].tv = ((float)lpSrc->bottom) / fHgt;
  607.  
  608.         // g_ss.nGradZ is an angle in grades, so calculate radians
  609.         RotRadZ = (float) (g_ss.nGradZ++) * pi / 180.f;
  610.         if( !g_ss.bRotateZ)
  611.         {
  612.             g_ss.nGradZ--;
  613.         }
  614.  
  615.         RotRadY = (float) (g_ss.nGradY++) * pi / 180.f;
  616.         if( !g_ss.bRotateY)
  617.         {
  618.             g_ss.nGradY--;
  619.         }
  620.  
  621.         // to avoid stack overflow, limit counters withing 360 grades
  622.         if( g_ss.nGradZ > 360) 
  623.         {
  624.             g_ss.nGradZ = 0;
  625.         }
  626.  
  627.         if( g_ss.nGradY > 360) 
  628.         {
  629.             g_ss.nGradY = 0;
  630.         }
  631.     
  632.         // and finally rotate the primitive pVertices
  633.         // NOTE that rotation center is hardcoded for the case 
  634.         // 640x480 display mode
  635.         Rotate(RotRadZ, RotRadY, pVertices, 4, 320.f, 240.f);
  636.     }
  637.  
  638.     //----------------------------------------------------------------------------
  639.     // PrepareVerticesTwist
  640.     //
  641.     // This is the 'main' transformation function for "twist" effect.
  642.     // It generates transformation parameters 'time' variable that is just
  643.     // a static counter of images from CMpegMovie:PresentImage function
  644.     //
  645.     // Parameters:
  646.     //          lpDst   - destination rectangle
  647.     //          lpSrc   - source rectangle
  648.     //          alpha   - alpha level for the surface
  649.     //          fWid    - width of the surface obtained by CMpegMovie:PresentImage
  650.     //          fHgt    - height of the surface obtained by CMpegMovie:PresentImage
  651.     //
  652.     // Other:   put your own effects here
  653.     //          The effect I use is as following:
  654.     //          (a) move picture down to create 'slipping' effect
  655.     //          (b) srink lower part of the picture (parameter c applied to each verticle
  656.     //              so that it would look like a wine glass stem (cosine is what we need)
  657.     //              Shrinking coefficient depends on Y-coordinate of a verticle
  658.     //          (c) twist lower part of the picture around Y axis, angle depends on 
  659.     //              Y-coordinate of a verticle
  660.     //----------------------------------------------------------------------------
  661.     void PrepareVerticesTwist(  RECT* lpDst, RECT* lpSrc, BYTE alpha,
  662.                                 float fW, float fH)
  663.     {
  664.         CAlphaBlt::Vertex * V = pVComplex;
  665.         float W = (float)(lpDst->right - lpDst->left);
  666.         float H = (float)(lpDst->bottom - lpDst->top);
  667.         float sW = (float)(lpSrc->right - lpSrc->left)/fW;
  668.         float sH = (float)(lpSrc->bottom - lpSrc->top);
  669.         float Ht = 480 - H;
  670.         float c;
  671.         float radY = 0.f;
  672.         float radX = pi/4.f;
  673.         float x;
  674.         double costh;
  675.         double sinth;
  676.         D3DXMATRIX  mtrPrs;
  677.         D3DXMATRIX  mtrOrg;
  678.         D3DXMATRIX  mtrRes;
  679.  
  680.         int N = COMPLVERTSIZE/2;
  681.  
  682.         g_ss.nDy = g_ss.nDy + 3;
  683.         if( g_ss.nDy > 480 )
  684.         {
  685.             g_ss.nDy = 0;
  686.         }
  687.  
  688.         for( int i=0; i<COMPLVERTSIZE; i=i+2)
  689.         {
  690.             V[i  ].x   = (float)(lpDst->left);
  691.             V[i+1].x   = (float)(lpDst->right);
  692.             V[i  ].y   = V[i+1].y = (float)(i * H/(N-1)) + g_ss.nDy;
  693.             V[i  ].z   = V[i+1].z = 0.5f;
  694.             V[i  ].rhw = V[i+1].rhw = 2.f;
  695.             V[i  ].clr = V[i+1].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
  696.             V[i  ].tu  = ((float)lpSrc->left) / fW;
  697.             V[i+1].tu  = ((float)lpSrc->right) / fW;
  698.             V[i  ].tv  = V[i+1].tv = (float)(lpSrc->top + sH * (float)i/(N-1.f)/2.f)/fH;
  699.             
  700.             
  701.             if( V[i].y >= H )
  702.             {
  703.                 
  704.                 c = (float)( W * (1. + cos(pi * (480. - V[i].y)/Ht)) / 4.);
  705.                 //c *= 0.25f;
  706.                 V[i  ].x += c;
  707.                 V[i+1].x -= c;
  708.                 
  709.                 radY = pi * ( V[i].y - H ) / 2.f / Ht;
  710.  
  711.                 costh = cos(radY);
  712.                 sinth = sin(radY);
  713.  
  714.                 x = V[i].x - 320.f;
  715.                 V[i].x = (float)(costh * x - sinth * V[i].z) + 320.f;
  716.                 V[i].z = (float)(sinth * x + costh * V[i].z);
  717.  
  718.                 x = V[i+1].x - 320.f;
  719.                 V[i+1].x = (float)(costh * x - sinth * V[i+1].z) + 320.f;
  720.                 V[i+1].z = (float)(sinth * x + costh * V[i+1].z);
  721.                                 
  722.             } // if
  723.  
  724.         }// for i
  725.  
  726.         
  727.         // now let's implement projection
  728.         D3DXMatrixPerspectiveFov( &mtrPrs, pi/2.f, 1.1f, 0.f, 1.f);
  729.         for( i=0; i<COMPLVERTSIZE; i = i+4)
  730.         {
  731.             mtrOrg.m[0][0] = V[i].x;
  732.             mtrOrg.m[1][0] = V[i].y;
  733.             mtrOrg.m[2][0] = V[i].z;
  734.             mtrOrg.m[3][0] = 0.f;
  735.  
  736.             mtrOrg.m[0][1] = V[i+1].x;
  737.             mtrOrg.m[1][1] = V[i+1].y;
  738.             mtrOrg.m[2][1] = V[i+1].z;
  739.             mtrOrg.m[3][1] = 0.f;
  740.  
  741.             mtrOrg.m[0][2] = V[i+2].x;
  742.             mtrOrg.m[1][2] = V[i+2].y;
  743.             mtrOrg.m[2][2] = V[i+2].z;
  744.             mtrOrg.m[3][2] = 0.f;
  745.  
  746.             mtrOrg.m[0][3] = V[i+3].x;
  747.             mtrOrg.m[1][3] = V[i+3].y;
  748.             mtrOrg.m[2][3] = V[i+3].z;
  749.             mtrOrg.m[3][3] = 0.f;
  750.  
  751.             D3DXMatrixMultiply( &mtrRes, &mtrPrs, &mtrOrg);
  752.  
  753.             V[i  ].x = mtrRes.m[0][0];
  754.             V[i  ].y = mtrRes.m[1][0];
  755.             V[i  ].z = mtrRes.m[2][0];
  756.  
  757.             V[i+1].x = mtrRes.m[0][1];
  758.             V[i+1].y = mtrRes.m[1][1];
  759.             V[i+1].z = mtrRes.m[2][1];
  760.  
  761.             V[i+2].x = mtrRes.m[0][2];
  762.             V[i+2].y = mtrRes.m[1][2];
  763.             V[i+2].z = mtrRes.m[2][2];
  764.  
  765.             V[i+3].x = mtrRes.m[0][3];
  766.             V[i+3].y = mtrRes.m[1][3];
  767.             V[i+3].z = mtrRes.m[2][3];
  768.         }// for
  769.         
  770.         return;
  771.     }
  772.  
  773.     //----------------------------------------------------------------------------
  774.     // AlphaBlt
  775.     // 
  776.     // This function receives LPDIRECTDRAWSURFACE7 from ImagePresenter, calls
  777.     // transformation functions to provide visual effects, sets the scene and
  778.     // renders primitives
  779.     //
  780.     // Parameters: 
  781.     //      lpDst    -- destination rectangle
  782.     //      lpDDSSrc -- surface obtained by ImagePresenter
  783.     //      lpSrc    -- source rectangle
  784.     //      bAlpha   -- alpha value for the surface
  785.     //----------------------------------------------------------------------------
  786.     HRESULT
  787.     AlphaBlt(RECT* lpDst,
  788.              LPDIRECTDRAWSURFACE7 lpDDSSrc,
  789.              RECT* lpSrc,
  790.              BYTE  bAlpha
  791.              )
  792.     {
  793.         HRESULT hr=S_OK;
  794.         DDSURFACEDESC2 ddsd;
  795.  
  796.         int nVertSize = 0;
  797.  
  798.         CAlphaBlt::Vertex * pV = NULL; 
  799.  
  800.         __try {
  801.  
  802.             INITDDSTRUCT(ddsd);
  803.             CHECK_HR(hr = lpDDSSrc->GetSurfaceDesc(&ddsd));
  804.  
  805.             if (!IsSurfaceBlendable(ddsd, bAlpha)) {
  806.                 CHECK_HR(hr = MirrorSourceSurface(lpDDSSrc, ddsd));
  807.                 lpDDSSrc = m_lpDDMirror;
  808.             }
  809.             
  810.             float fWid = (float)ddsd.dwWidth;
  811.             float fHgt = (float)ddsd.dwHeight;
  812.  
  813.             if( g_ss.bShowTwist )
  814.             {
  815.                 nVertSize = COMPLVERTSIZE;
  816.                 PrepareVerticesTwist(lpDst, lpSrc, bAlpha, fWid, fHgt);
  817.                 pV = pVComplex;
  818.             }
  819.             else
  820.             {
  821.                 nVertSize = 4;
  822.                 PrepareVerticesRotate(lpDst, lpSrc, bAlpha, fWid, fHgt);
  823.                 pV = pVertices;
  824.             }
  825.  
  826.             BYTE alpha = bAlpha;
  827.  
  828.             m_pD3DDevice->SetTexture(0, lpDDSSrc);
  829.             // if menu is defined, set it
  830.  
  831.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
  832.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, TRUE);
  833.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_BLENDENABLE, TRUE);
  834.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
  835.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
  836.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
  837.  
  838.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  839.  
  840.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_ANISOTROPIC);
  841.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC);
  842.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
  843.  
  844.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  845.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
  846.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  847.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  848.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  849.     
  850.             //
  851.             // Do the alpha BLT
  852.             //
  853.             CHECK_HR(hr = m_pD3DDevice->BeginScene());
  854.             CHECK_HR(hr = m_pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,0.5,0));
  855.             CHECK_HR(hr = m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
  856.                                                     D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1,
  857.                                                     pV, nVertSize, D3DDP_WAIT));
  858.  
  859.             // now, draw menu over the video
  860.             
  861.             // if user switched modes, menu texture may be lost; then restore
  862.             if( m_bNeedToRestoreMenu )
  863.             {
  864.                 DDSURFACEDESC2 ddsd;
  865.                 ZeroMemory( &ddsd, sizeof(ddsd));
  866.                 ddsd.dwSize = sizeof(ddsd);
  867.                 ddsd.dwFlags = DDSD_ALL;
  868.                 m_pDD->GetDisplayMode( &ddsd);
  869.  
  870.                 // if we try to restore surface in a different display mode, we will fail
  871.                 // so make the check first
  872.                 if( ddsd.dwWidth == SCRN_WIDTH && 
  873.                     ddsd.dwHeight == SCRN_HEIGHT && 
  874.                     ddsd.ddpfPixelFormat.dwRGBBitCount == SCRN_BITDEPTH )
  875.                 {
  876.                     hr = GetMenuTexture()->Restore();
  877.                     if( FAILED(hr))
  878.                     {
  879.                         OutputDebugString("ERROR: Failed to restore menu texture");
  880.                     }
  881.                     else
  882.                     {
  883.                         // surface restored, but its image lost; reload
  884.                         if( m_ptxtrMenu) 
  885.                         {
  886.                             hr = m_ptxtrMenu->LoadImageData();
  887.                             if( FAILED(hr))
  888.                             {
  889.                                 OutputDebugString("Failed to load the image from resource\n");
  890.                             }
  891.                             if( m_ptxtrMenu->m_hbmBitmap )
  892.                             {
  893.                                 BITMAP bm;
  894.                                 GetObject( m_ptxtrMenu->m_hbmBitmap, sizeof(BITMAP), &bm );
  895.                                 m_ptxtrMenu->m_dwWidth  = (DWORD)bm.bmWidth;
  896.                                 m_ptxtrMenu->m_dwHeight = (DWORD)bm.bmHeight;
  897.                                 m_ptxtrMenu->m_dwBPP    = (DWORD)bm.bmBitsPixel;
  898.                             }
  899.         
  900.                             hr = m_ptxtrMenu->Restore(m_pD3DDevice);
  901.                             if( FAILED(hr))
  902.                             {
  903.                                 delete m_ptxtrMenu;
  904.                                 m_ptxtrMenu = NULL;
  905.                             }
  906.                         }
  907.  
  908.                         m_bNeedToRestoreMenu = false;
  909.                     }
  910.                 }
  911.                 else
  912.                 {
  913.                     OutputDebugString("Failed to restore menu texture");
  914.                 }
  915.             }
  916.  
  917.             m_pD3DDevice->SetTexture(0, m_ptxtrMenu->m_pddsSurface);
  918.  
  919.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  920.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_ANISOTROPIC);
  921.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC);
  922.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
  923.             // 
  924.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  925.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
  926.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  927.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  928.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  929.  
  930.             CHECK_HR(hr = m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
  931.                                                     D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1,
  932.                                                     pVMenu, 4, D3DDP_WAIT));
  933.             m_pD3DDevice->SetTexture(0, NULL);
  934.  
  935.             // and if necessary, draw the dext over the menu
  936.             if( g_ss.bShowHelp )
  937.             {
  938.                 HRESULT hr = m_pFont->DrawText((float)g_ss.nXHelp, (float)g_ss.nYHelp,
  939.                                                 RGBA_MAKE(0xFF, 0xFF, 0x00, 0xFF),
  940.                                                 g_ss.achHelp );
  941.             }
  942.             if( g_ss.bShowStatistics )
  943.             {
  944.                 m_pFont->DrawText(  420, 0, 
  945.                                     RGBA_MAKE(0x00, 0xFF, 0x00, 0xFF),
  946.                                     g_ss.achFPS );
  947.             }
  948.  
  949.             CHECK_HR(hr = m_pD3DDevice->EndScene());
  950.  
  951.         } __finally {
  952.             m_pD3DDevice->SetTexture(0, NULL);
  953.         }
  954.  
  955.         return hr;
  956.     }
  957.  
  958.     //----------------------------------------------------------------------------
  959.     // TextureSquare
  960.     // true if texture is square
  961.     //----------------------------------------------------------------------------
  962.     bool TextureSquare() {
  963.         return  m_fSquare;
  964.     }
  965.  
  966.     //----------------------------------------------------------------------------
  967.     // TexturePower2
  968.     // true if texture size is of a power of 2
  969.     //----------------------------------------------------------------------------
  970.     bool TexturePower2() {
  971.         return  m_fPowerOf2;
  972.     }
  973.  
  974. };
  975.  
  976.  
  977.